/* Copyright (c) 2011 Timothée Lacroix
 * This file is part of HINAPT.
 *
 * HINAPT is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * HINAPT is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with HINAPT.  If not, see <http://www.gnu.org/licenses/>.
 */


 #include "thresholdFeature.hpp"

bool Triplet::operator<(const Triplet &a)const{
  return evaluation<a.evaluation;
}

bool ThFeature::save(ostream &output){
  f.save(output);
  output<<" "<<threshold<<" "<<inf<<" ";
  return !output.fail();

}

bool ThFeature::load(istream &input){
  f.load(input);
  input>>threshold;
  input>>inf;
  return !input.fail();
}

ThFeature::ThFeature(Feature a,vector<Mat>& pos,
                     vector<Mat>& neg,vector<double>& poids){
  f=a;
  vector<Triplet> total;
  for(int i=0;i<(int)pos.size();i++)
      total.push_back(Triplet(evalFeature(f.x1,f.y1,f.x2,f.y2,f.numero,pos[i]),
                              1,poids[i]));

  for(int i=0;i<(int)neg.size();i++)
      total.push_back(Triplet(evalFeature(f.x1,f.y1,f.x2,f.y2,f.numero,neg[i]),
                              -1,poids[i+pos.size()]));

  sort(total.begin(),total.end());

  vector<double> cumul1(total.size()+1,0);
  vector<double> cumul2(total.size()+1,0);

  for(int i=1;i<=(int)total.size();i++){
    cumul1[i]=cumul1[i-1]+double((1-total[i-1].val)/2)*total[i-1].poids;
    cumul2[i]=cumul2[i-1]+double((total[i-1].val+1)/2)*total[i-1].poids;
  }
  double minErr=INFINI;
  for(int i=0;i<(int)total.size();i++){
    if(i==(int)total.size()-1 || total[i].evaluation!=total[i+1].evaluation){
      double val=cumul2[i+1]+(cumul1[total.size()]-cumul1[i+1]);
      if(val<minErr){
        threshold=total[i].evaluation;
        inf=false;
        minErr=val;
      }
      //on essaie la seconde polarisation
      val=cumul1[i+1]+(cumul2[total.size()]-cumul2[i+1]);
      if(val<minErr){
        threshold=total[i].evaluation;
        inf=true;
        minErr=val;
      }
    }
  }
}

double ThFeature::error(vector<Mat>& pos,vector<Mat>& neg,
                        vector<double>& poids,bool print){
  int fauxNeg=0;
  int fauxPos=0;
  double error=0;
  for(int i=0;i<(int)pos.size();i++){
    if(eval(pos[i])==-1){
      error+=poids[i];
      fauxNeg++;
    }
  }

  for(int i=0;i<(int)neg.size();i++){
    if(eval(neg[i])==1){
      error+=poids[i+pos.size()];
      fauxPos++;
    }
  }
  if(print)
    printf("----- fauxPos = %d  || fauxNeg = %d \n",fauxPos,fauxNeg);
  return error;
}

int ThFeature::eval(Mat img,double weight){
  int val=weight*evalFeature(f.x1,f.y1,f.x2,f.y2,f.numero,img);
  if(inf && val<threshold)
    return 1;
  if(!inf && val >threshold)
    return 1;
  return -1;
}
